{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "regional-bedroom",
   "metadata": {},
   "source": [
    "# Experiments with `start_time`"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "quantitative-radar",
   "metadata": {},
   "source": [
    "This notebook introduces functionality for simulating user case in which the experiment steps are triggered at a certain point in time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "novel-spectacular",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m23.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m23.1.2\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
      "Note: you may need to restart the kernel to use updated packages.\n"
     ]
    }
   ],
   "source": [
    "%pip install \"pybamm[plot,cite]\" -q    # install PyBaMM if it is not installed\n",
    "from datetime import datetime\n",
    "\n",
    "import pybamm"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "11c87da1",
   "metadata": {},
   "source": [
    "Let's start defining a model to illustrate this functionality, in this case we choose the SPM"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "96b62a7f",
   "metadata": {},
   "outputs": [],
   "source": [
    "model = pybamm.lithium_ion.SPM()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "f388d538",
   "metadata": {},
   "source": [
    "Usually we define an experiment such that each step is triggered when the previous step is completed. For example, in this case we do a 1C discharge for 20 minutes and then a C/3 charge for 10 minutes. The charge step starts after 20 minutes, i.e. once the discharge step is finished."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "eba027c8",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "86a9137722254204893ad9cf3402c6df",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=0.0, description='t', max=1800.0, step=18.0), Output()), _dom_classes=…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<pybamm.plotting.quick_plot.QuickPlot at 0x7f8910adb4f0>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "experiment = pybamm.Experiment(\n",
    "    [\"Discharge at 1C for 20 minutes\", \"Charge at C/3 for 10 minutes\"]\n",
    ")\n",
    "sim = pybamm.Simulation(model, experiment=experiment)\n",
    "sim.solve()\n",
    "sim.plot()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "0fdfced4",
   "metadata": {},
   "source": [
    "However, if we want to represent a realistic user case we might certain experiments to be run at a certain time instead, even if that means cutting short the previous step. In this case we can pass a starting time as a keyword argument in the `pybamm.step.string` method. The `start_time` should be passed as a `datetime.datetime` object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "171550ac",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "a22e45e9e8ff46b194efe28b21f7a9a6",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "interactive(children=(FloatSlider(value=0.0, description='t', max=2.5, step=0.025), Output()), _dom_classes=('…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "<pybamm.plotting.quick_plot.QuickPlot at 0x7f8910b8e250>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "s = pybamm.step.string\n",
    "\n",
    "experiment = pybamm.Experiment(\n",
    "    [\n",
    "        s(\"Discharge at 1C for 1 hour\", start_time=datetime(1, 1, 1, 8, 0, 0)),\n",
    "        s(\"Charge at C/3 for 10 minutes\", start_time=datetime(1, 1, 1, 8, 30, 0)),\n",
    "        s(\"Discharge at C/2 for 30 minutes\", start_time=datetime(1, 1, 1, 9, 0, 0)),\n",
    "        s(\"Rest for 1 hour\"),\n",
    "    ]\n",
    ")\n",
    "sim = pybamm.Simulation(model, experiment=experiment)\n",
    "sim.solve()\n",
    "sim.plot()"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "edfa4c9f",
   "metadata": {},
   "source": [
    "In the example above, we note that the first step (1C discharge) is cut short as the second step (C/3 charge) start time occurs before the end of the first step. On the other hand, an additional resting period is added after the second step as the third step (C/2 discharge) start time is 20 minutes later than the end of the second step. The final step does not have a start time so it is triggered immediately after the previous step. Note that if the argument `start_time` is used in an experiment, the first step should always have a `start_time`, otherwise the solver will throw an error."
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "fff78a14",
   "metadata": {},
   "source": [
    "Note that you can use the `datetime.strptime` (see [the docs](https://docs.python.org/3/library/datetime.html#datetime.datetime.strptime) for more info) function to convert a string to a datetime object. For example, to start the experiment at 8:30 on the 2nd of January 2023, you can use"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "bb616043",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "datetime.datetime(2023, 1, 2, 8, 30)"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "datetime.strptime(\"2023-01-02 8:30:00\", \"%Y-%m-%d %H:%M:%S\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "driven-sensitivity",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1] Joel A. E. Andersson, Joris Gillis, Greg Horn, James B. Rawlings, and Moritz Diehl. CasADi – A software framework for nonlinear optimization and optimal control. Mathematical Programming Computation, 11(1):1–36, 2019. doi:10.1007/s12532-018-0139-4.\n",
      "[2] Charles R. Harris, K. Jarrod Millman, Stéfan J. van der Walt, Ralf Gommers, Pauli Virtanen, David Cournapeau, Eric Wieser, Julian Taylor, Sebastian Berg, Nathaniel J. Smith, and others. Array programming with NumPy. Nature, 585(7825):357–362, 2020. doi:10.1038/s41586-020-2649-2.\n",
      "[3] Scott G. Marquis, Valentin Sulzer, Robert Timms, Colin P. Please, and S. Jon Chapman. An asymptotic derivation of a single particle model with electrolyte. Journal of The Electrochemical Society, 166(15):A3693–A3706, 2019. doi:10.1149/2.0341915jes.\n",
      "[4] Peyman Mohtat, Suhak Lee, Jason B Siegel, and Anna G Stefanopoulou. Towards better estimability of electrode-specific state of health: decoding the cell expansion. Journal of Power Sources, 427:101–111, 2019.\n",
      "[5] Valentin Sulzer, Scott G. Marquis, Robert Timms, Martin Robinson, and S. Jon Chapman. Python Battery Mathematical Modelling (PyBaMM). Journal of Open Research Software, 9(1):14, 2021. doi:10.5334/jors.309.\n",
      "[6] Pauli Virtanen, Ralf Gommers, Travis E. Oliphant, Matt Haberland, Tyler Reddy, David Cournapeau, Evgeni Burovski, Pearu Peterson, Warren Weckesser, Jonathan Bright, and others. SciPy 1.0: fundamental algorithms for scientific computing in Python. Nature Methods, 17(3):261–272, 2020. doi:10.1038/s41592-019-0686-2.\n",
      "[7] Andrew Weng, Jason B Siegel, and Anna Stefanopoulou. Differential voltage analysis for battery manufacturing process control. arXiv preprint arXiv:2303.07088, 2023.\n",
      "\n"
     ]
    }
   ],
   "source": [
    "pybamm.print_citations()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "593ae90b",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.17"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  },
  "vscode": {
   "interpreter": {
    "hash": "612adcc456652826e82b485a1edaef831aa6d5abc680d008e93d513dd8724f14"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
